package com.socct.lib_compler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.auto.service.AutoService;
import com.socct.navigation.ActivityDestination;
import com.socct.navigation.FragmentDestination;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.FileObject;
import javax.tools.StandardLocation;

@AutoService(Processor.class)
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes({"com.socct.navigation.ActivityDestination", "com.socct.navigation.FragmentDestination"})
public class NavProcessor extends AbstractProcessor {

    private Messager messager;
    private Filer filer;
    public static final String OUTPUT_FIFLE_NAME = "destination.json";

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        messager = processingEnvironment.getMessager();
        filer = processingEnv.getFiler();
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {

        Set<? extends Element> fragment = roundEnvironment.getElementsAnnotatedWith(FragmentDestination.class);
        Set<? extends Element> activity = roundEnvironment.getElementsAnnotatedWith(ActivityDestination.class);
        HashMap<String, JSONObject> map = new HashMap<>();
        messager.printMessage(Diagnostic.Kind.ERROR, "开始开始开始开始开始开始");
        if (fragment != null && !fragment.isEmpty()) {
            handleDestination(fragment, FragmentDestination.class, map);
        }
        if (activity != null && !activity.isEmpty()) {
            handleDestination(activity, ActivityDestination.class, map);
        }
        System.out.println("----------------------------------------------------------------");
        messager.printMessage(Diagnostic.Kind.ERROR, "--------------------------------------------------");
        if (!map.isEmpty()) {
            FileOutputStream fos = null;
            OutputStreamWriter writer = null;
            try {
                FileObject resource = filer.createResource(StandardLocation.CLASS_OUTPUT, "", OUTPUT_FIFLE_NAME);
                String resourcePath = resource.toUri().getPath();
                String appPath = resourcePath.substring(0, resourcePath.indexOf("app") + 4);
                String assetsPath = appPath + "src/main/assets";
                File file = new File(assetsPath);
                if (!file.exists()) {
                    file.mkdirs();
                }
                File outPutFile = new File(file, OUTPUT_FIFLE_NAME);
                if (!outPutFile.exists()) {
                    outPutFile.delete();
                }
                outPutFile.createNewFile();
                String json = JSON.toJSONString(map);
                fos = new FileOutputStream(outPutFile);
                writer = new OutputStreamWriter(fos);
                writer.write(json);
                writer.flush();
            } catch (IOException e) {
                messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage());
                e.printStackTrace();
            } finally {
                close(fos);
                close(writer);
            }
        }

        return true;
    }


    private void close(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void handleDestination(Set<? extends Element> elements, Class<? extends Annotation> ann, HashMap<String, JSONObject> map) {
        for (Element element : elements) {
            TypeElement typeElement = (TypeElement) element;
            String pageUrl = null;
            String className = typeElement.getQualifiedName().toString();
            int id = Math.abs(className.hashCode());
            boolean needLoging = false;
            boolean asStart = false;
            boolean isFragment = false;
            Annotation annotation = typeElement.getAnnotation(ann);
            if (annotation instanceof FragmentDestination) {
                FragmentDestination dest = (FragmentDestination) annotation;
                pageUrl = dest.pagerUrl();
                isFragment = true;
                asStart = dest.asStart();
                needLoging = dest.needLogin();
            } else if (annotation instanceof ActivityDestination) {
                ActivityDestination dest = (ActivityDestination) annotation;
                isFragment = false;
                pageUrl = dest.pagerUrl();
                asStart = dest.asStart();
                needLoging = dest.needLogin();
            }
            if (map.containsKey(pageUrl)) {
                messager.printMessage(Diagnostic.Kind.ERROR, "不同的页面不允许使用相同的pageUrl");
            } else {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("pageUrl", pageUrl);
                jsonObject.put("className", className);
                jsonObject.put("id", id);
                jsonObject.put("needLoging", needLoging);
                jsonObject.put("asStart", asStart);
                jsonObject.put("isFragment", isFragment);
                map.put(pageUrl, jsonObject);
            }

        }


    }
}
